#!/usr/bin/perl

use strict;
use Diff;
use Getopt::Long;
use Utilities qw( green magenta bold white highlight );

my $opts = {};
GetOptions($opts, 'highlight');

main();

sub main {

  foreach my $file (@ARGV) {
    die("$0: $file: $!\n") unless(-f $file);
  }

  open(my $fh, '<', $ARGV[0]) or die("FILE1: $!\n");
  my @old = <$fh>;
  close($fh);

  open(my $fh, '<', $ARGV[1]) or die("FILE2: $!\n");
  my @new = <$fh>;
  close($fh);

  my $diff = Diff->new(\@old, \@new);

  $diff->Base(1);    # Return line numbers, not indices
  while($diff->Next()) {
    next if $diff->Same();

    if(!$diff->Items(2)) {
      printf green("%d,%dd%d\n"), $diff->Get(qw( Min1 Max1 Max2 ));
      print magenta("< $_") for $diff->Items(1);
    } elsif (!$diff->Items(1)) {
      printf green("%da%d,%d\n"), $diff->Get(qw( Max1 Min2 Max2 ));
      print bold(white("> $_")) for $diff->Items(2);
    } else {
      printf green("%d,%dc%d,%d\n"), $diff->Get(qw( Min1 Max1 Min2 Max2 ));
      inline_diff($diff);
    }
  }
}

sub inline_diff {
  my ($diff) = @_;

  my @old = $diff->Items(1);
  my @new = $diff->Items(2);

  if($opts->{'highlight'}) {
    foreach my $ln (0 .. $#old) {
      my @o = split(//, $old[$ln], -1);
      my @n = split(//, $new[$ln], -1);
      my $line_diff = Diff->new(\@o, \@n);
      my %found;
      while($line_diff->Next()) {
        next if($line_diff->Same());
        if(!$line_diff->Items(2)) {
          my ($start, $end) = $line_diff->Get(qw(Min1 Max1));
          $o[$_] = highlight($o[$_]) foreach $start .. $end;
        } elsif (!$line_diff->Items(1)) {
          my ($start, $end) = $line_diff->Get(qw(Min2 Max2));
          $n[$_] = highlight($n[$_]) foreach $start .. $end;
        } else {
          my ($start, $end) = $line_diff->Get(qw(Min1 Max1));
          $o[$_] = highlight($o[$_]) foreach $start .. $end;

          ($start, $end) = $line_diff->Get(qw(Min2 Max2));
          $n[$_] = highlight($n[$_]) foreach $start .. $end;
        }
      }

      $old[$ln] = join('', @o);
      $new[$ln] = join('', @n);
    }
  }

  print magenta("< $_") for @old;
  print green("----\n");
  print bold(white("> $_")) for @new;
}
